/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.statemachine.helper;

import java.util.Iterator;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.FinalState;
import org.eclipse.uml2.uml.Region;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.Vertex;

import com.cea.papyrus.core.helper.NodeHelper;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.statemachine.Activator;
import com.cea.papyrus.diagram.statemachine.preference.StateMachineDiagramPreferenceConstants;
import com.cea.papyrus.diagraminterchange2.di2.DiagramElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Manages FinalState.
 * 
 * @author David Servat
 * @since 29 jan. 07
 */
public class NodeFinalStateHelper extends NodeHelper{

	/**
	 * The channel.
	 */
	private int channel = 501;

	/**
	 * 
	 * 
	 * @param umlChild 
	 * @param size 
	 * @param location 
	 * @param parent 
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#createGraphElement(org.eclipse.uml2.uml.Element, com.cea.papyrus.diagraminterchange2.di2.GraphElement, org.eclipse.draw2d.geometry.Point, org.eclipse.draw2d.geometry.Dimension)
	 */
	@Override
	public GraphNode createGraphElement(Element umlChild, GraphElement parent, Point location, Dimension size){
		Debug.debug(this,"Call GraphNode NodeFinalStateHelper.createGraphElement(Element umlChild, GraphElement parent, Point location, Dimension size)", channel); //$NON-NLS-1$

		//caution: must pass a null argument for umlParent to the super class method
		//otherwise the graph node is directly added!!
		//we adjust the size to the strict dimension of the icon figure
		if((size == null) || size.equals(getGraphNodeSize()))
			size = new Dimension(16, 16);
		GraphNode graphNode = super.createGraphElement(umlChild, null, location, size);
		//adjust the position so that node is centered beneath the mouse pointer
		Point centeredLocation = graphNode.getPosition().getCopy();
		Dimension dims = graphNode.getSize().getCopy();
		if(size.equals(16, 16))
			centeredLocation.translate(-dims.width/2, -dims.height/2);
		graphNode.setPosition(centeredLocation.getCopy());

		GraphNode labelNode = super.createGraphElement(null, null, new Point(centeredLocation.x,centeredLocation.y+graphNode.getSize().height+5), null);
		labelNode.setSemanticParent(graphNode);
	    labelNode.setContainer(parent);
	    labelNode.setIsVisible(false);
	    
		//the ge parent is connected in last becaus an event may be sent at this moment and trigger a refresh.
		if(parent != null)
			parent.getContained().add(graphNode);
		return graphNode;
	}
	
	/**
	 * 
	 * 
	 * @param child 
	 * @param parent 
	 * 
	 * @return 
	 */
	public boolean undoCreateGraphElement(GraphElement child, GraphElement parent){
		child.setSemanticParent(null);
		child.eAdapters().clear();
		Iterator<DiagramElement> itchild=child.getSemanticChild().iterator();
		for(int i=0; i<child.getSemanticChild().size();){
			GraphElement subchild=(GraphElement)child.getSemanticChild().get(i);
			subchild.eAdapters().clear();
			subchild.setSemanticParent(null);
			subchild.getContainer().getContained().remove(subchild);
		}
		child.getContainer().getContained().remove(child);
		return true;
	}



	/**
	 * 
	 * 
	 * @param parent 
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#canCreateGraphElement(com.cea.papyrus.diagraminterchange2.di2.GraphElement)
	 */
	@Override
	public boolean canCreateGraphElement(GraphElement parent){
		Debug.debug(this,"Call boolean NodeFinalStateHelper.cancreateGraphElement(GraphElement parent)", channel);

		//this method is called when the State button was clicked on the palette
		//and the mouse cursor is moved across a diagram
		//it says whether (true,false) a State can be created as child of the underlying element
		//the only case here is when hovering over a Region
		if(parent.getSemanticModel() != null){
			Element parentElt= ((Uml1SemanticModelBridge)parent.getSemanticModel()).getElement();
			if(parentElt != null){
				if(parentElt instanceof Region) {
					return true;
				}
			}
		}
		return false;
	}

	///////////////////////////////////////////////////////////////////////////
	// UML Management
	///////////////////////////////////////////////////////////////////////////

	/**
	 * 
	 * 
	 * @param umlParent 
	 * @param name 
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#createUMLElement(java.lang.String, org.eclipse.uml2.uml.Element)
	 */
	@Override
	public Element createUMLElement(String name, Element umlParent){
		Debug.debug(this,"Call Element NodeFinalStateHelper.createUMLElement(String name, Element umlParent)", channel); //$NON-NLS-1$
		FinalState aState = UMLFactory.eINSTANCE.createFinalState();
		aState.setName(name);
		((Region)umlParent).getSubvertices().add(aState);
		return aState;
	}

	/**
	 * 
	 * 
	 * @param umlParent 
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#canCreateUMLElement(org.eclipse.uml2.uml.Element)
	 */
	@Override
	public boolean canCreateUMLElement(Element umlParent){
		Debug.debug(this,"Call boolean NodeFinalStateHelper.canCreateUMLElement(Element umlParent)", channel); //$NON-NLS-1$
		if(umlParent instanceof Region)
			return true;
		return false;
	}

	/**
	 * 
	 * 
	 * @param element 
	 * @param umlParent 
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#addUMLElement(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	@Override
	public boolean addUMLElement(Element element, Element umlParent){
		Debug.debug(this,"Call boolean NodeFinalStateHelper.addUMLElement(Element element, Element umlParent)", channel); //$NON-NLS-1$
		if(umlParent instanceof Region)
			return ((Region)umlParent).getSubvertices().add((Vertex)element);
		return false;
	}

	/**
	 * 
	 * 
	 * @param element 
	 * @param umlParent 
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#removeUMLElement(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	@Override
	public boolean removeUMLElement(Element element, Element umlParent){
		Debug.debug(this,"Call boolean NodeFinalStateHelper.removeUMLElement(Element element, Element umlParent)", channel); //$NON-NLS-1$
		if(umlParent instanceof Region)
			return ((Region)umlParent).getSubvertices().remove(element);
		return false;
	}

	/**
	 * 
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#getBaseString()
	 */
	@Override
	public String getBaseString(){
		return "FinalState_"; //$NON-NLS-1$
	}

	/**
	 * 
	 * 
	 * @param umlParent 
	 * 
	 * @return 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#getNewUMLElementName(org.eclipse.uml2.uml.Element)
	 */
	@Override
	public String getNewUMLElementName(Element umlParent){
		String name = ""; //$NON-NLS-1$

		//i <10000: avoid infinite loops
		for(int i=0; i< 10001; i++ ){
			name = getBaseString()+i;
			if(umlParent == null)
				return name;
			if(((Region)umlParent).getSubvertex(name) == null)
				return name;
		}
		return getBaseString()+"X"; //$NON-NLS-1$
	}

	/**
	 * 
	 * 
	 * @param graphElement 
	 * 
	 * @see com.cea.papyrus.common.helper.NodeHelper#setGraphElementPreferences(com.cea.papyrus.diagraminterchange2.di2.GraphElement)
	 */
	@Override
	public void setGraphElementPreferences(GraphElement graphElement){
		//get the preference store
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();

		//set colors and font
		graphElement.setBackgroundColor(StateMachineDiagramPreferenceConstants.getPreferenceFinalStateBackgroundColor(store));
		graphElement.setBorderColor(StateMachineDiagramPreferenceConstants.getPreferenceFinalStateBorderColor(store));
		graphElement.setFontColor(StateMachineDiagramPreferenceConstants.getPreferenceFinalStateFontColor(store));
		FontData[] fontdata = StateMachineDiagramPreferenceConstants.getPreferenceFinalStateFont(store);
		if(fontdata.length>0){
			graphElement.setFontFamily(fontdata[0].getName());
			graphElement.setFontSize(fontdata[0].getHeight());
		}
	}
}